/*
 * ========THE SOLMIX PROJECT=====================================
 *
 * This is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as
 * published by the Free Software Foundation; either version 2.1 of
 * the License, or (at your option) any later version.
 *
 * This software is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser General Public License for more details.
 *
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * http://www.gnu.org/licenses/ 
 * or see the FSF site: http://www.fsf.org. 
 */

package org.solmix.fmk.util;

import java.util.LinkedList;

import javax.servlet.ServletContext;

import org.osgi.framework.BundleContext;
import org.osgi.service.event.Event;
import org.osgi.service.event.EventAdmin;
import org.solmix.SLXConstants;
import org.solmix.commons.logs.Logger;
import org.solmix.fmk.config.ConfigRealm;
import org.solmix.fmk.config.impl.ConfigRealmWebImpl;
import org.solmix.fmk.datasource.DataSourceManager;
import org.solmix.fmk.repo.DSRepoManager;
import org.solmix.fmk.repo.FileSystemDSRepo;
import org.solmix.fmk.servlet.ServletTools;
import org.solmix.services.datasource.DataSourceManagerService;
import org.solmix.services.exception.SLXException;
import org.solmix.services.repo.DSRepoService;
import org.solmix.services.types.Texception;
import org.solmix.services.types.Tmodule;

/**
 * @version $Id$
 */
public class OSGIHelper
{

    private static Logger log = new Logger(OSGIHelper.class.getName());
    private static BundleContext context;

    private static LinkedList<ConfigRealm> configRealms = new LinkedList<ConfigRealm>();

    private static LinkedList<DataSourceManagerService> dsmanagers = new LinkedList<DataSourceManagerService>();

    private static LinkedList<DSRepoService> dsrepos = new LinkedList<DSRepoService>();

    public static volatile ConfigRealm CM;

    public static volatile ServletContext servletContext = null;

    public static volatile DataSourceManagerService DSM;

    public static volatile DSRepoService DSR;

    public static volatile EventAdmin eventAdmin;

    
    /**
     * @return the context
     */
    public static BundleContext getContext() {
        return context;
    }

    
    /**
     * @param context the context to set
     */
    public void setContext(BundleContext context) {
        OSGIHelper.context = context;
    }

    public synchronized void register_eventAdmin(EventAdmin eventAdmin) {
        OSGIHelper.eventAdmin = eventAdmin;
    }

    public synchronized void unregister_eventAdmin(EventAdmin eventAdmin) {
        OSGIHelper.eventAdmin = null;
    }

    public synchronized void register_cm(ConfigRealm configRealm) {
        configRealms.push(configRealm);
        refresh_cm();

    }

    public synchronized void unregister_cm(ConfigRealm configRealm) {
        configRealms.pop();
        refresh_cm();
    }

    public synchronized void register_dsm(DataSourceManagerService dsmanager) {
        dsmanagers.push(dsmanager);
        refresh_dsm();

    }

    public synchronized void unregister_dsm(DataSourceManagerService dsmanager) {
        dsmanagers.pop();
        refresh_dsm();
    }

    public synchronized void register_dsr(DSRepoService dsrepo) {
        dsrepos.push(dsrepo);
        refresh_dsr();

    }

    public synchronized void unregister_dsr(DSRepoService dsrepo) {
        dsrepos.pop();
        refresh_dsr();
    }

    private synchronized void refresh_cm() {
        if (configRealms != null && configRealms.size() >= 1)
            CM = configRealms.getFirst();
    }

    /**
     * @return the cM
     */
    public static ConfigRealm getCM() {

        return getCM(SLXConstants.MODULE_DS_NAME);
    }

    public static ConfigRealm getCM(String realmName) {
        if (SLXConstants.isOSGI()) {
            log.debug("use the OSGI container to find out configuration manager service");
            ConfigRealm CM = null;
            for (ConfigRealm realm : configRealms) {
                String name = realm.getName();
                if (name != null && name.equals(realmName)) {
                    CM = realm;
                }
            }
            try {
                if (CM == null) {
                    throw new SLXException(Tmodule.CONFIG, Texception.OSGI_SERVICE_UNAVAILABLE,
                        "osgi config service is unavalable");
                }
            } catch (SLXException e) {
                log.error(e.getMessage());
            }
            return CM;

        } else {
            log.debug("Not under OSGI-ENV ,use default configuration manager service implementation.");
            CM = new ConfigRealmWebImpl();
        }
        return CM;
    }

    /**
     * @return the dSM
     */
    public static DataSourceManagerService getDSM() {
        if (DSM == null && SLXConstants.isOSGI()) {
            try {
                throw new SLXException(Tmodule.DATASOURCE, Texception.OSGI_SERVICE_UNAVAILABLE,
                    "osgi DataSourceManagerService is unavalable");
            } catch (SLXException e) {
                log.error(e.getMessage());
            }
            log.debug("use the OSGI container to find out datasource manager service");
        } else {
            if (DSM == null) {
                log.debug("Not under OSGI-ENV ,use default datasource manager service implementation.");
                DSM = new DataSourceManager();
            }
        }
        return DSM;
    }

    public static EventAdmin getEventAdmin() {
        return eventAdmin;
    }
    public static void fireEvent(Event event)
    {
        if(eventAdmin!=null){
            eventAdmin.postEvent(event);
        }
    }
    /**
     * @return the dSR
     */
    public static DSRepoService getDSR() {
        if (DSR == null && SLXConstants.isOSGI()) {
            try {
                throw new SLXException(Tmodule.REPO, Texception.OSGI_SERVICE_UNAVAILABLE,
                    "osgi DSRepoService is unavalable");
            } catch (SLXException e) {
                log.error(e.getMessage());
            }
            log.debug("use the OSGI container to find out datasource repository service");
        } else {
            if (DSR == null) {
                log.debug("Not under OSGI-ENV ,use default datasource repository  service implementation.");
                DSRepoManager repoManager = new DSRepoManager();
                String repoLoacation = "";
                try {
                    repoLoacation = ServletTools.getContainerPath(servletContext) + "datasource";
                } catch (SLXException e) {
                    log.error(e.getMessage());
                }
                FileSystemDSRepo repo = new FileSystemDSRepo();
                repo.setLocation(repoLoacation);
                repoManager.setDefaultRepo(repo);
                DSR = repoManager;
            }
        }
        return DSR;
    }

    private synchronized void refresh_dsm() {
        if (dsmanagers != null && dsmanagers.size() >= 1)
            DSM = dsmanagers.getFirst();
    }

    private synchronized void refresh_dsr() {
        if (dsrepos != null && dsrepos.size() >= 1)
            DSR = dsrepos.getFirst();
    }

}
